from django.shortcuts import render, redirect
from django.views import View
from django.http import JsonResponse, HttpResponseForbidden
from django import http
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
import logging
from django.contrib.auth import login
import re
from django_redis import get_redis_connection

from meiduo_mall.utils.response_code import RETCODE
from .models import OAuthQQUser
from .utils import generate_openid_signature, check_openid_sign
from users.models import User

# Create your views here.
logger = logging.getLogger('django')

class OAuthURLView(View):
    """构建QQ登陆页面url"""
    # this.host + '/qq/authorization/?next=' + next;前端请求
    def get(self,request):
        # 提取参数，来源
        next = request.GET.get('next', '/')
        # 调用QQtool 返回构建的URL
        qq_auth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                          client_secret=settings.QQ_CLIENT_SECRET,
                          redirect_uri=settings.QQ_REDIRECT_URI,
                          state=next)
        login_url = qq_auth.get_qq_url()

        return JsonResponse({"login_url": login_url, "code": RETCODE.OK, "errmsg": "ok"})

# 用户在QQ登录成功后，QQ会将用户重定向到我们配置的回调网址。
# 在QQ重定向到回调网址时，会传给我们一个Authorization Code。
# 我们需要拿到Authorization Code并完成OAuth2.0认证获取openid。
# QQ互联重定向的完整网址为：
# http://www.meiduo.site:8000/oauth_callback/?code=AE263F12675FA79185B54870D79730A7&state=%2F

class QQAuthView(View):
    """用户扫码登陆的回调处理"""
    def get(self,request):
        next = request.GET.get('state')
        code = request.GET.get('code')
        if not code:
            return HttpResponseForbidden('缺少code')

        #使用code获取access_token值
        qq_auth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                          client_secret=settings.QQ_CLIENT_SECRET,
                          redirect_uri=settings.QQ_REDIRECT_URI,
                          state=next)
        try:
            access_token = qq_auth.get_access_token(code)

            # 使用token 获取 openid
            openid = qq_auth.get_open_id(access_token)
        except Exception as e:
            logger.error(e)
            return JsonResponse({'code': RETCODE.SERVERERR, 'errmsg': 'QQ服务器不可用'})

        # return JsonResponse({"openid": openid})


        # user绑定openid, 通过openid查询OAuthQQUser模型
        try:
            oauth_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:

            # 如果没有查询到，先重定向到绑定页面创建新user绑定
            # openid 需要保存到前端 不然重定向就结束销毁了
            #保存前端前需要加密敏感数据
            openid = generate_openid_signature(openid)
            # return render(request, 'oauth_callback.html', {'openid', openid})
            return render(request, 'oauth_callback.html', {'openid': openid})

        # 如果有查到user，说明是已绑定的用户，直接登陆
        else:
            #  外键
            user = oauth_user.user
            # 状态保持
            login(request, user)
            response = redirect(next)
            response.set_cookie('username', user.username, max_age=3600*24*14)
            return response


    def post(self, request):
        """实现openid绑定用户逻辑"""
        # 接收数据
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        sms_code = request.POST.get('sms_code')
        openid = request.POST.get('openid')

        if all([mobile, password, sms_code, openid]) is False:
            return http.HttpResponseForbidden('缺少必传参数')


        # 校验
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('您输入的手机号格式不正确')

        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('请输入8-20位的密码')

        # 短信验证码校验后期再补充
        redis_coon = get_redis_connection('verify_code')
        sms_code_server = redis_coon.get('sms_%s' % mobile)  # 获取redis中的短信验证码

        if sms_code_server is None or sms_code != sms_code_server.decode():
            return http.HttpResponseForbidden('短信验证码有误')

        # 校验openid
        openid = check_openid_sign(openid)
        if openid is None:
            return http.HttpResponseForbidden('openid无效')

        # 绑定用户
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 当前要绑定的用户是一个新用户
            user = User.objects.create_user(
                username=mobile,
                password=password,
                mobile=mobile,
            )
        else:
            # 当前要绑定的用户是已存在
            if user.check_password(password) is False:
                return http.HttpResponseForbidden('账号或密码错误')

        # 如果代码能执行到这里,用户user绝对已经有了
        # 用户openid和user绑定
        OAuthQQUser.objects.create(
            user=user,
            openid=openid
        )

        # 重定向
        login(request, user)
        response = redirect(request.GET.get('state'))
        response.set_cookie('username', user.username, max_age=settings.SESSION_COOKIE_AGE)
        return response

